﻿using Modbus.Device;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace sync_signal_light.subs
{
    public class mdbs
    {
        private IModbusMaster NMaster = null;
        private IModbusMaster AlmMaster = null;
        private SerialPort DevPort;
        private SerialPort AlarmPort;
        private string DevHead = "", AlarmHead = "";

        public void AlarmControlTask()
        {
            //预留报警采集功能
            AlarmPort = new SerialPort();
            AlarmPort.Close();
            AlarmPort.PortName = opini.CLS_CFG.alarm_port;
            AlarmPort.BaudRate = 9600;
            AlarmPort.DataBits = 8;
            AlarmPort.Parity = Parity.None;
            AlarmPort.StopBits = StopBits.One;

            AlarmPort.Open();
            AlarmHead = "(" + opini.CLS_CFG.alarm_port + "-" + AlarmPort.BaudRate.ToString() + "-" + AlarmPort.DataBits.ToString() + "-" + AlarmPort.Parity.ToString() + "-" + AlarmPort.StopBits.ToString() + ")";
            int IDX = 0;
            while (true)
            {
                Thread.Sleep(opini.CLS_CFG.alarm_delay);
                try
                {
                    opini.CLS_ALARM = Json.Deserialize<cls_alarm_control>(opini.read_config("ALARM", "control"));
                    if (opini.CLS_ALARM == null)
                    {
                        opini.CLS_ALARM = new cls_alarm_control();
                        opini.write_config("ALARM", "control", Json.Serialize(opini.CLS_ALARM));
                    }
                    if ((opini.AlarmCode > 0)||(opini.AlarmLose>0))
                    {
                        switch (IDX)
                        {
                            case 0:
                                if (opini.CLS_ALARM.open_light.Count >= 8)
                                {
                                    byte[] sends = opini.CLS_ALARM.open_light.ToArray();
                                    AlarmPort.Write(sends, 0, sends.Length);
                                    IDX++;
                                }
                                break;
                            case 1:
                                if (opini.CLS_ALARM.open_beer.Count >= 8)
                                {
                                    byte[] sends = opini.CLS_ALARM.open_beer.ToArray();
                                    AlarmPort.Write(sends, 0, sends.Length);
                                    IDX++;
                                }
                                break;
                            default:
                                IDX = 0;
                                break;
                        }
                    }
                    else
                    {
                        switch (IDX)
                        {
                            case 0:
                                if (opini.CLS_ALARM.close_light.Count >= 8)
                                {
                                    byte[] sends = opini.CLS_ALARM.close_light.ToArray();
                                    AlarmPort.Write(sends, 0, sends.Length);
                                    IDX++;
                                }
                                break;
                            case 1:
                                if (opini.CLS_ALARM.close_beer.Count >= 8)
                                {
                                    byte[] sends = opini.CLS_ALARM.close_beer.ToArray();
                                    AlarmPort.Write(sends, 0, sends.Length);
                                    IDX++;
                                }
                                break;
                            default:
                                IDX = 0;
                                break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    //记录日志
                    opini.cprint(AlarmHead + "报警通讯异常：" + ex.Message);
                }
            }
        }

        public void LightCollectTask()
        {
            DevPort = new SerialPort();
            DevPort.Close();
            DevPort.PortName = opini.CLS_CFG.light_port;
            DevPort.BaudRate = 9600;
            DevPort.DataBits = 8;
            DevPort.Parity = Parity.None;
            DevPort.StopBits = StopBits.One;
            //
            NMaster = ModbusSerialMaster.CreateRtu(DevPort);
            NMaster.Transport.WaitToRetryMilliseconds = 20;
            NMaster.Transport.Retries = 3;
            NMaster.Transport.ReadTimeout = 200;
            DevPort.Open();
            DevHead = "(" + opini.CLS_CFG.light_port + "-" + DevPort.BaudRate.ToString() + "-" + DevPort.DataBits.ToString() + "-" + DevPort.Parity.ToString() + "-" + DevPort.StopBits.ToString() + ")";
            int IDX = 0;
            int address = 0;
            bool get_config = true;
            while (true)
            {
                try
                {
                    if (opini.DicDevs == null) continue;
                    if (opini.DicDevs.Count == 0) continue;
                    if (opini.CLS_PARA.auto == false) continue;
                    if (opini.CLS_PARA.cwt.Count > 0)//写入设备数据
                    {
                        opini.cprint(DevHead + "写入设备" + opini.CLS_PARA.cwt[0].address.ToString() + string.Format("   TX:{0} {1} {2} {3}", opini.CLS_PARA.cwt[0].address, 06, opini.CLS_PARA.cwt[0].reister, opini.CLS_PARA.cwt[0].value));
                        NMaster.WriteSingleRegister((byte)opini.CLS_PARA.cwt[0].address, (ushort)opini.CLS_PARA.cwt[0].reister, (ushort)opini.CLS_PARA.cwt[0].value);
                        opini.cprint(DevHead + "写入设备" + opini.CLS_PARA.cwt[0].address.ToString() + "成功");
                        Thread.Sleep(200);
                        opini.CLS_PARA.cwt.RemoveAt(0);
                        get_config = true;
                        continue;
                    }
                    for (int i = 0; i < opini.CLS_CFG.addrs.Count; i++)
                    {
                        try
                        {
                            if (opini.CLS_PARA.cwt.Count > 0) break;//有写入的时候跳出轮训                                                              
                            try { address = int.Parse(opini.CLS_CFG.addrs[i]); } catch { address = 1; }  //轮询读取设备数据
                            IDX = i;
                            if (get_config)//获取设备参数
                            {
                                opini.cprint(DevHead + "读取设备" + address.ToString() + string.Format(" 参数   TX:{0} {1} {2} {3}", address, 03, 01, 9));
                                ushort[] registers = NMaster.ReadHoldingRegisters((byte)address, 1, 9);
                                if (registers != null)
                                {
                                    opini.cprint(DevHead + "读取设备" + address.ToString() + " 参数   RX:" + string.Join(",", registers.ToArray()));
                                    if (registers.Length < 8)
                                    {
                                        opini.cprint(DevHead + "读取设备" + address.ToString() + " 参数 数据失败,接收数据长度异常");
                                    }
                                    else
                                    {
                                        //解析数据
                                        if (opini.DicDevs.ContainsKey(address) == false) continue;
                                        opini.DicDevs[address].light_level = registers[0];
                                        opini.DicDevs[address].day_enable = registers[1];
                                        opini.DicDevs[address].day_light = registers[2];
                                        opini.DicDevs[address].day_cycle = registers[3];
                                        opini.DicDevs[address].day_delay = registers[4];
                                        opini.DicDevs[address].night_enable = registers[5];
                                        opini.DicDevs[address].night_light = registers[6];
                                        opini.DicDevs[address].night_cycle = registers[7];
                                        opini.DicDevs[address].night_delay = registers[8];

                                    }
                                }
                            }
                            else
                            { //获取状态
                                opini.cprint(DevHead + "读取设备" + address.ToString() + string.Format(" 状态   TX:{0} {1} {2} {3}", address, 03, 11, 4));
                                ushort[] registers = NMaster.ReadHoldingRegisters((byte)address, 11, 4);
                                if (registers != null)
                                {
                                    opini.cprint(DevHead + "读取设备" + address.ToString() + " 状态   RX:" + string.Join(",", registers.ToArray()));
                                    if (registers.Length < 3)
                                    {
                                        opini.cprint(DevHead + "读取设备" + address.ToString() + " 状态  数据失败,接收数据长度异常");
                                    }
                                    else
                                    {
                                        //解析数据
                                        if (opini.DicDevs.ContainsKey(address) == false) continue;
                                        int alamcode = registers[0];
                                        opini.DicDevs[address].light_now = registers[1];
                                        opini.DicDevs[address].gps_count = registers[3];
                                        if (alamcode == 0)
                                        {
                                            opini.AlarmCode &= ~(1 << IDX);
                                            opini.DicDevs[address].status = "正常";
                                        }
                                        else
                                        {
                                            opini.DicDevs[address].status = "异常:";
                                            if ((alamcode & 0x0001) > 0) opini.DicDevs[address].status += "光感故障;";
                                            if ((alamcode & 0x0002) > 0) opini.DicDevs[address].status += "GPS故障;";
                                            if ((alamcode & 0x0004) > 0) opini.DicDevs[address].status += "RS485总线故障;";
                                            if ((alamcode & 0x0005) > 0) opini.DicDevs[address].status += "连续漏闪大于4次;";
                                            opini.AlarmCode |= (1 << IDX);
                                        }

                                    }
                                }
                                opini.AlarmLose &= ~(1 << IDX);//正常
                            }
                        }
                        catch (Exception ex)
                        {
                            if (opini.CLS_PARA.cwt.Count > 0)//写入设备数据
                            {
                                if (opini.CLS_PARA.cwt[0].address != 0)
                                {
                                    opini.cprint(DevHead + "写入设备" + opini.CLS_PARA.cwt[0].address.ToString() + "  失败");
                                    opini.AlarmLose |= (1 << IDX);
                                }
                                else
                                {
                                    opini.cprint(DevHead + "广播写入" + opini.CLS_PARA.cwt[0].address.ToString() + "  完成");
                                }
                                opini.CLS_PARA.cwt.RemoveAt(0);
                            }
                            else
                            {

                                opini.AlarmLose |= (1 << IDX);
                                opini.cprint(DevHead + "读取设备：" + address.ToString() + " ERROR! " + ex.Message);
                            }
                            continue;
                        }
                    }
                    if (get_config) get_config = false;
                    else Thread.Sleep(opini.CLS_CFG.light_delay);

                    /*
                    //轮询读取设备数据
                    try { address = int.Parse(opini.CLS_CFG.addrs[IDX]); } catch { address = 1; }
                    //读取保持寄存器
                    opini.cprint(DevHead + "读取设备" + address.ToString() + string.Format("   TX:{0} {1} {2} {3}", address, 03, 01, 16));
                    ushort[] registers = NMaster.ReadHoldingRegisters((byte)address, 1, 16);
                    if (registers != null)
                    {
                        opini.cprint(DevHead + "读取设备" + address.ToString() + "   RX:" + string.Join(",", registers.ToArray()));
                        if (registers.Length < 15)
                        {
                            opini.cprint(DevHead + "读取设备" + address.ToString() + "数据失败,接收数据长度异常");
                        }
                        else
                        {
                            //解析数据
                            if (opini.DicDevs.ContainsKey(address) == false) continue;
                            opini.DicDevs[address].light_level = registers[0];
                            opini.DicDevs[address].day_enable = registers[1];
                            opini.DicDevs[address].day_light = registers[2];
                            opini.DicDevs[address].day_cycle = registers[3];
                            opini.DicDevs[address].day_delay = registers[4];
                            opini.DicDevs[address].night_enable = registers[5];
                            opini.DicDevs[address].night_light = registers[6];
                            opini.DicDevs[address].night_cycle = registers[7];
                            opini.DicDevs[address].night_delay = registers[8];
                            int alamcode = registers[10];
                            opini.DicDevs[address].light_now = registers[11];
                            opini.DicDevs[address].gps_count = registers[13];
                            if (alamcode == 0)
                            {
                                opini.AlarmCode &= ~(1 << IDX);
                                opini.DicDevs[address].status = "正常";
                            }
                            else
                            {
                                opini.DicDevs[address].status = "异常:";
                                if ((alamcode & 0x0001) > 0) opini.DicDevs[address].status += "光感故障;";
                                if ((alamcode & 0x0002) > 0) opini.DicDevs[address].status += "GPS故障;";
                                if ((alamcode & 0x0004) > 0) opini.DicDevs[address].status += "RS485总线故障;";
                                if ((alamcode & 0x0005) > 0) opini.DicDevs[address].status += "连续漏闪大于4次;";
                                opini.AlarmCode |= (1 << IDX);
                            }

                        }
                        opini.AlarmLose &= ~(1 << IDX);//正常
                        if (++IDX >= opini.CLS_CFG.addrs.Count) IDX = 0;
                    }
                    else
                    {
                        opini.AlarmLose |= (1 << IDX);//异常
                        opini.cprint(DevHead + "读取设备" + address.ToString() + "数据失败，没有数据返回");
                        if (++IDX >= opini.CLS_CFG.addrs.Count) IDX = 0;

                    }
                    */
                }
                catch (Exception ex)
                {
                    //记录日志
                    opini.cprint(" ERROR! " + ex.Message);
                }

            }
        }
        public void ClosePorts()
        {
            try
            {
                if (DevPort != null)
                {
                    if (DevPort.IsOpen) DevPort.Close();
                }
                if (AlarmPort != null)
                {
                    if (AlarmPort.IsOpen) AlarmPort.Close();
                }
            }
            catch
            {
                opini.cprint("关闭串口！");
            }
        }
    }
}
